package org.mozhu.mboot.core.config;

import org.mozhu.mboot.core.config.database.DatabasePropertySourceBeanFactoryPostProcessor;
import org.mozhu.mboot.core.config.jasypt.JasyptEncryptAutoConfiguration;
import org.mozhu.mboot.core.config.support.SimpleConfigurationListener;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.core.Ordered;
import org.springframework.core.env.ConfigurableEnvironment;

@Configuration
@ConditionalOnBean(ApplicationConfigurationMarkerConfiguration.Marker.class)
@AutoConfigureBefore(value = {PropertyPlaceholderAutoConfiguration.class, WebMvcAutoConfiguration.class})
@Import(JasyptEncryptAutoConfiguration.class)
public class ApplicationConfigurationAutoConfiguration {

    public final static int LOWEST_PRECEDENCE_H = Ordered.LOWEST_PRECEDENCE - 2;
    public final static int LOWEST_PRECEDENCE_M = Ordered.LOWEST_PRECEDENCE - 1;
    public final static int LOWEST_PRECEDENCE_L = Ordered.LOWEST_PRECEDENCE;

    @Bean
    public ApplicationConfiguration applicationConfiguration(PropertySourcesPlaceholderConfigurer configurer) {
        ApplicationConfiguration applicationConfiguration = ApplicationConfiguration.get();
        applicationConfiguration.init(configurer);
        applicationConfiguration.addListener(new SimpleConfigurationListener());
        return applicationConfiguration;
    }

    /**
     * Make sure these three BeanFactoryPostProcessors are invoked in below order:
     * 1. PriorityOrderedEnableEncryptablePropertiesBeanFactoryPostProcessor
     * 2. DatabasePropertySourceBeanFactoryPostProcessor
     * 3. PropertySourcesPlaceholderConfigurer
     */

    @Bean
    public static DatabasePropertySourceBeanFactoryPostProcessor applicationConfigurationBeanFactoryPostProcessor(ConfigurableEnvironment configurableEnvironment) {
        return new DatabasePropertySourceBeanFactoryPostProcessor(configurableEnvironment) {
            @Override
            public int getOrder() {
                return LOWEST_PRECEDENCE_M;
            }
        };
    }

    @Bean
    public static DefaultPropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer(ConfigurableEnvironment configurableEnvironment) {
        return new DefaultPropertySourcesPlaceholderConfigurer(configurableEnvironment) {
            @Override
            public int getOrder() {
                return LOWEST_PRECEDENCE_L;
            }
        };
    }

}
